package cn.tannn.cat.file.server.controller.manage;

import cn.tannn.cat.file.server.controller.manage.dto.EditStorageConfig;
import cn.tannn.cat.file.server.controller.manage.dto.StorageConfig;
import cn.tannn.cat.file.server.controller.manage.dto.StorageConfigAppend2;
import cn.tannn.cat.file.server.controller.manage.dto.StorageConfigPage;
import cn.tannn.cat.file.server.controller.manage.vo.FileStorageConfigVO;
import cn.tannn.cat.file.server.entity.FileStorageConfig;
import cn.tannn.cat.file.server.service.FileStorageConfigService;
import cn.tannn.cat.file.server.service.StorageBucketService;
import cn.tannn.jdevelops.annotations.web.mapping.PathRestController;
import cn.tannn.jdevelops.exception.built.BusinessException;
import cn.tannn.jdevelops.jpa.result.JpaPageResult;
import cn.tannn.jdevelops.result.response.ResultPageVO;
import cn.tannn.jdevelops.result.response.ResultVO;
import cn.tannn.jdevelops.result.utils.ListTo;
import com.alibaba.fastjson2.JSONObject;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Sort;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 存储器配置
 *
 * @author tnnn
 * @version V1.0
 * @date 2024-03-09 20:34
 */
@Tag(name = "存储器配置管理", description = "存储器配置管理")
@PathRestController("config")
@RequiredArgsConstructor
@Slf4j
@Valid
public class StorageConfigController {

    private final FileStorageConfigService fileStorageConfigService;
    private final StorageBucketService storageBucketService;

    @Operation(summary = "新增存储器")
    @PostMapping("append")
    public ResultVO<String> append(@RequestBody @Valid StorageConfig append) {
        fileStorageConfigService.append(append.toFileConfig());
        return ResultVO.successMessage("存储器新增成功");
    }

    @Operation(summary = "新增存储器2 - config-new.json 用的")
    @PostMapping("append2")
    public ResultVO<String> append2(@RequestBody @Valid StorageConfigAppend2 append) {
        fileStorageConfigService.append(append.toFileConfig());
        return ResultVO.successMessage("存储器新增成功");
    }

    @Operation(summary = "查询存储器-分页")
    @PostMapping("page")
    public ResultPageVO<FileStorageConfigVO, JpaPageResult<FileStorageConfigVO>> page(@RequestBody @Valid StorageConfigPage page) {
        Page<FileStorageConfig> storages = fileStorageConfigService.findPage(page, page.getPage());
        JpaPageResult<FileStorageConfigVO> re = JpaPageResult.toPage(storages, FileStorageConfigVO.class);
        return ResultPageVO.success(re, "查询成功");
    }

    @Operation(summary = "删除存储器", description = "不允许删除启用中的配置，存在文件的不允许删除")
    @DeleteMapping("delete")
    @Parameter(name = "id", description = "编号", required = true)
    public ResultVO<String> delete(@RequestParam("id") Long id) {
        fileStorageConfigService.delete(id);
        // 删除桶
        storageBucketService.deleteEq("configId", id);
        return ResultVO.successMessage("存储器删除成功");
    }

    @Operation(summary = "设置master", description = "会将其他master置为从，因为只允许有一个master")
    @PutMapping("changeMaster")
    @Parameter(name = "id", description = "编号", required = true)
    public ResultVO<String> changeMaster(@RequestParam("id") Long id) {
        fileStorageConfigService.changeMaster(id);
        return ResultVO.successMessage("成功设置master");
    }

    @Operation(summary = "查询存储器")
    @GetMapping("list")
    public ResultVO<List<FileStorageConfigVO>> listStorages() {
        List<FileStorageConfig> storageConfigs = fileStorageConfigService.getJpaBasicsDao().findAll(Sort.by("id"));
        List<FileStorageConfigVO> vos = ListTo.to(FileStorageConfigVO.class, storageConfigs);
        return ResultVO.success(vos);
    }


    @Operation(summary = "编辑存储器配置")
    @PostMapping("edit/{id}")
    public ResultVO<String> edit(@PathVariable("id") Long id, @RequestBody @Valid EditStorageConfig edit) {
        fileStorageConfigService
                .findOnly("id", id)
                .ifPresent(update -> {
                    if (edit.getConfig() != null && !edit.getConfig().isEmpty()) {
                        FileStorageConfig fileConfig = edit.toFileConfig(update);
//                        log.error("更新存储器配置:{}", fileConfig);
                        fileStorageConfigService.updateData(fileConfig);
                    }
                });
        return ResultVO.successMessage("修改成功");
    }


    @Operation(summary = "查询存储器")
    @GetMapping("info/{id}")
    public ResultVO<FileStorageConfigVO> info(@PathVariable("id") Long id) {
        FileStorageConfig fileStorageConfig = fileStorageConfigService
                .findOnly("id", id)
                .orElseThrow(() -> new BusinessException("存储器配置不存在"));
        return ResultVO.success(fileStorageConfig.to(FileStorageConfigVO.class));
    }


    @Operation(summary = "查询存储器Json信息")
    @GetMapping("infoJson/{id}")
    public ResultVO<JSONObject> infoJson(@PathVariable("id") Long id) {
        FileStorageConfig fileStorageConfig = fileStorageConfigService
                .findOnly("id", id)
                .orElseThrow(() -> new BusinessException("存储器配置不存在"));
        return ResultVO.success(fileStorageConfig.getConfig());
    }


    /**
     * 前端动态获取存储器配置的schema
     * @param storage 存储器类型
     * @return 输入框结构
     */
    @GetMapping("/schema")
    public ResultVO<Object> getConfigSchema(@RequestParam("storage") String storage) {
        Map<String, Object> schema = new HashMap<>();

        switch (storage) {
            case "60": // FTP
                schema.put("type", "combo");
                schema.put("name", "config");
                schema.put("label", Map.of(
                        "type", "tooltip-wrapper",
                        "content", "与<mm style='color:red'>字典值</mm>联动",
                        "body", "ftp配置",
                        "className", "mb-1"
                ));
                schema.put("multiLine", true);
                schema.put("items", List.of(
                        Map.of(
                                "name", "browseUrl",
                                "type", "input-text",
                                "label", Map.of(
                                        "type", "tooltip-wrapper",
                                        "content", "<mm style='color:red'>http/https</mm>nginx代理的接口地址或者本身的访问地址<注意最后不要有斜杠>[http://192.168.1.71:8200]",
                                        "body", "文件预览地址",
                                        "className", "mb-1"
                                ),
                                "required", true
                        ),
                        Map.of(
                                "name", "hostname",
                                "type", "input-text",
                                "label", Map.of(
                                        "type", "tooltip-wrapper",
                                        "content", "<mm style='color:red'>e.g. 192.168.0.1</mm>",
                                        "body", "服务器IP",
                                        "className", "mb-1"
                                ),
                                "required", true
                        ),
                        Map.of(
                                "name", "port",
                                "type", "select",
                                "creatable", true,
                                "selectFirst", true,
                                "label", Map.of(
                                        "type", "tooltip-wrapper",
                                        "content", "ftp服务器端口号默认为<mm style='color:red'>21</mm>",
                                        "body", "服务器端口",
                                        "className", "mb-1"
                                ),
                                "options", List.of(Map.of("label", "21", "value", 21))
                        ),
                        Map.of(
                                "name", "username",
                                "type", "input-text",
                                "label", "登录账号",
                                "required", false
                        ),
                        Map.of(
                                "name", "password",
                                "type", "input-text",
                                "label", "登录密码",
                                "required", false
                        ),
                        Map.of(
                                "name", "usePrefix",
                                "type", "input-text",
                                "label", "文件使用前缀，自定义的 FileOperateApi#views 接口前缀[默认：/operation/ftpviews/]",
                                "description", "ftp是特殊的,为了上传之后的 UrlSuffix 和 Url 所以需要写",
                                "required", false
                        )
                ));
                break;

            case "30": // AWS S3
                schema.put("type", "combo");
                schema.put("name", "config");
                schema.put("label", Map.of(
                        "type", "tooltip-wrapper",
                        "content", "与<mm style='color:red'>字典值</mm>联动",
                        "body", "AWS3配置",
                        "className", "mb-1"
                ));
                schema.put("multiLine", true);
                schema.put("items", List.of(
                        Map.of(
                                "name", "browseUrl",
                                "type", "input-text",
                                "label", Map.of(
                                        "type", "tooltip-wrapper",
                                        "content", "<mm style='color:red'>AWS S3的文件浏览地址前缀</mm>[https://sda.xx.com]",
                                        "body", "文件预览地址",
                                        "className", "mb-1"
                                ),
                                "required", true
                        ),
                        Map.of(
                                "name", "accessKey",
                                "type", "input-text",
                                "label", "access",
                                "required", true
                        ),
                        Map.of(
                                "name", "secretKey",
                                "type", "input-text",
                                "label", "secret",
                                "required", true
                        ),
                        Map.of(
                                "name", "regionId",
                                "type", "select",
                                "creatable", true,
                                "selectFirst", true,
                                "label", Map.of(
                                        "type", "tooltip-wrapper",
                                        "body", Map.of(
                                                "type", "link",
                                                "href", "https://docs.aws.amazon.com/zh_cn/AWSEC2/latest/UserGuide/using-regions-availability-zones.html#concepts-regions",
                                                "body", "区域"
                                        ),
                                        "className", "mb-1"
                                ),
                                "options", List.of(
                                        Map.of("label", "us-east-1", "value", "us-east-1"),
                                        Map.of("label", "us-west-1", "value", "us-west-1"),
                                        Map.of("label", "us-east-2", "value", "us-east-2")
                                )
                        )
                ));
                break;

            case "40": // 七牛
                schema.put("type", "combo");
                schema.put("name", "config");
                schema.put("label", Map.of(
                        "type", "tooltip-wrapper",
                        "content", "与<mm style='color:red'>字典值</mm>联动",
                        "body", "七牛配置",
                        "className", "mb-1"
                ));
                schema.put("multiLine", true);
                schema.put("items", List.of(
                        Map.of(
                                "name", "browseUrl",
                                "type", "input-text",
                                "label", Map.of(
                                        "type", "tooltip-wrapper",
                                        "content", "<mm style='color:red'>七牛云的文件浏览地址前缀</mm>[https://sda.xx.com]",
                                        "body", "文件预览地址",
                                        "className", "mb-1"
                                ),
                                "required", true
                        ),
                        Map.of(
                                "name", "https",
                                "type", "select",
                                "label", "https",
                                "selectFirst", true,
                                "options", List.of(
                                        Map.of("label", "是", "value", true),
                                        Map.of("label", "否", "value", false)
                                )
                        ),
                        Map.of(
                                "name", "accessKey",
                                "type", "input-text",
                                "label", "access",
                                "required", true
                        ),
                        Map.of(
                                "name", "secretKey",
                                "type", "input-text",
                                "label", "secret",
                                "required", true
                        ),
                        Map.of(
                                "name", "regionId",
                                "type", "select",
                                "creatable", true,
                                "selectFirst", true,
                                "label", Map.of(
                                        "type", "tooltip-wrapper",
                                        "body", Map.of(
                                                "type", "link",
                                                "href", "https://developer.qiniu.com/kodo/1671/region-endpoint-fq",
                                                "body", "区域"
                                        ),
                                        "className", "mb-1"
                                ),
                                "options", List.of(
                                        Map.of("label", "z0", "value", "z0"),
                                        Map.of("label", "z1", "value", "z1"),
                                        Map.of("label", "z2", "value", "z2")
                                )
                        )
                ));
                break;

            case "20": // MinIO
                schema.put("type", "combo");
                schema.put("name", "config");
                schema.put("label", Map.of(
                        "type", "tooltip-wrapper",
                        "content", "与<mm style='color:red'>字典值</mm>联动",
                        "body", "Minio配置",
                        "className", "mb-1"
                ));
                schema.put("multiLine", true);
                schema.put("items", List.of(
                        Map.of(
                                "name", "browseUrl",
                                "type", "input-text",
                                "label", Map.of(
                                        "type", "tooltip-wrapper",
                                        "content", "<mm style='color:red'>http/https</mm>minio访问地址前缀，注意最后不要有斜杠[https://oss.minio.com]",
                                        "body", "文件预览地址",
                                        "className", "mb-1"
                                ),
                                "required", true
                        ),
                        Map.of(
                                "name", "uploadUrl",
                                "type", "input-text",
                                "label", Map.of(
                                        "type", "tooltip-wrapper",
                                        "content", "<mm style='color:red'>不需要加http/https</mm>[oss.minio.com]",
                                        "body", "文件上传地址",
                                        "className", "mb-1"
                                ),
                                "required", true
                        ),
                        Map.of(
                                "name", "https",
                                "type", "select",
                                "label", "https",
                                "selectFirst", true,
                                "options", List.of(
                                        Map.of("label", "是", "value", true),
                                        Map.of("label", "否", "value", false)
                                )
                        ),
                        Map.of(
                                "name", "port",
                                "type", "select",
                                "creatable", true,
                                "selectFirst", true,
                                "label", Map.of(
                                        "type", "tooltip-wrapper",
                                        "content", "配置域名的情况下一般就不用写了",
                                        "body", "端口",
                                        "className", "mb-1"
                                ),
                                "options", List.of(
                                        Map.of("label", "443", "value", 443),
                                        Map.of("label", "80", "value", 80),
                                        Map.of("label", "9000", "value", 9000)
                                )
                        ),
                        Map.of(
                                "name", "accessKey",
                                "type", "input-text",
                                "label", "access",
                                "required", true
                        ),
                        Map.of(
                                "name", "secretKey",
                                "type", "input-text",
                                "label", "secret",
                                "required", true
                        )
                ));
                break;

            case "10": // Local
                schema.put("type", "combo");
                schema.put("name", "config");
                schema.put("label", Map.of(
                        "type", "tooltip-wrapper",
                        "content", "与<mm style='color:red'>字典值</mm>联动",
                        "body", "Local配置",
                        "className", "mb-1"
                ));
                schema.put("multiLine", true);
                schema.put("items", List.of(
                        Map.of(
                                "name", "browseUrl",
                                "type", "input-text",
                                "label", Map.of(
                                        "type", "tooltip-wrapper",
                                        "content", "<mm style='color:red'>http/https</mm>nginx代理的接口地址或者本身的访问地址前缀<注意最后不要有斜杠也不用加contextPath>[http://192.168.1.71:8200]",
                                        "body", "文件预览地址",
                                        "className", "mb-1"
                                ),
                                "required", true
                        ),
                        Map.of(
                                "name", "uploadDir",
                                "type", "input-text",
                                "label", Map.of(
                                        "type", "tooltip-wrapper",
                                        "content", "磁盘路径<mm style='color:red'>[E:/test/file]</mm>",
                                        "body", "存放路径",
                                        "className", "mb-1"
                                ),
                                "required", true
                        ),
                        Map.of(
                                "name", "contextPath",
                                "type", "input-text",
                                "label", Map.of(
                                        "type", "tooltip-wrapper",
                                        "content", "前端相对访问路径前缀 <mm style='color:red'>（e.g /image）</mm>",
                                        "body", "映射路径",
                                        "className", "mb-1"
                                ),
                                "required", true
                        )
                ));
                break;

            default:
                return ResultVO.success("暂不支持的存储类型");
        }

        return ResultVO.success(schema);
    }
}
